<template lang="html">
  <div class="player__wrapper">
    <div class="player__progress">
      <div class="time">
        <span class="time-now">{{currentTimeFmt}}</span>
        <span class="time-all">-{{leftTimeFmt}}</span>
      </div>
      <div class="player__progress-bar" ref="progressBar">
        <v-slider
          :style="{width: '100%'}"
          v-model="progress"
          :bufferValue="bufferedProgress"
          runwayColor="rgba(255,255,255,0.3)"
          barColor="#fff"
          buttonColor="#fff"
          :isloading="isloading"
          @change="changeProgress">
        </v-slider>
      </div>
    </div>
    <div class="player__btn-group" ref="playerBtnGroup">
      <div
        class="prev"
        :class="[isFirstAudio ? 'disabled' : '']"
        @click="prev">
      </div>
      <div
        ref="playBtn"
        :class="[!canPlay ? 'disabled' : '', !playing ? 'play' : 'pause']"
        @click="playOrPause">
      </div>
      <div
        class="next"
        :class="[isLastAudio ? 'disabled' : '']"
        @click="next">
      </div>
    </div>
    <audio ref="audiofile" :src="file" style="display: none;" preload="auto">
    Your browser does not support the audio tag.
    </audio>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
import VSlider from './slider/index'
import { fmtSecToMin } from './common/util'
import { eventTrack } from '../../util/decorator'

var ua = navigator.userAgent;
  // TODO 精确性待改进
var ANDROID = /android/i.test(ua);
var IOS = /iphone|ipad/i.test(ua);
var WP = /windows phone/i.test(ua);


interface dataModel {
  audio: any;
  file: string;
  canPlay: boolean;
  loaded: boolean;
  playing: boolean;
  bufferedProgress: number;
  progress: number;
  totalTime: number;
  currentTime: number;
  leftTime: number;
  step: number;
  sliderChangeInterval: any;
  bufferInterval: any;
  isloading: boolean;
  isfirstLoad: boolean;
}

export default Vue.extend({
  name: 'Player',

  data () {
    const initialState: dataModel = {
      audio: {},
      file: '',
      canPlay: true,
      loaded: false,
      playing: false,
      bufferedProgress: 0,
      progress: 0,
      totalTime: 0,
      currentTime: 0,
      leftTime: 0,
      step: 0,
      sliderChangeInterval: {},
      bufferInterval: {},
      isloading: false,
      isfirstLoad: true
    }
    return initialState
  },

  props: {
    isFirstAudio: {
      type: Boolean,
      default: true
    },
    isLastAudio: {
      type: Boolean,
      default: false
    }
  },

  computed: {
    currentTimeFmt ():string {
      return fmtSecToMin(this.currentTime)
    },

    leftTimeFmt ():string {
      return fmtSecToMin(this.leftTime)
    }
  },

  watch: {
    currentTime (val:number) {
      this.currentTimeFmt = fmtSecToMin(this.currentTime)
      this.leftTime = this.totalTime - this.currentTime
    }
  },

  components: {
    VSlider
  },

  mounted () {
    this.init()
  },

  destroyed () {
    this.clearItv()
    this.clearBufferItv()
  },

  methods: {
    init () {
      this.audio = this.$refs.audiofile
      this.audio.addEventListener('loadeddata', this._handleLoaded)
      this.audio.addEventListener('complete', this._handleComplete)
      this.audio.addEventListener('play', this._handlePlay)
      this.audio.addEventListener('canplay', this._handleCanPlay)
      // this.audio.addEventListener('progress', this._handleTimeupdate)
      this.setBufferItv()
    },

    _handleCanPlay () {
      console.log('canplay')
      const playBtn:any = this.$refs.playBtn
      this.canPlay = true
      playBtn.className.replace('disabled ', '')
    },

    _handleComplete () {
      // console.log('complete')
    },

    _handlePlay () {
      // console.log('_handlePlay')
    },

    _handleLoaded () {
      this.loaded = true
      this.leftTime = this.totalTime = this.audio.duration
      this.step = 1 / this.totalTime * 100
      // this._handleTimeupdate()
    },

    _handleTimeupdate () {
      let timeRange = this.audio.buffered
      let bufferedTime = timeRange.end(0) - timeRange.start(0)
      this.bufferedProgress = bufferedTime / this.totalTime * 100
    },

    changeAudio (url:string) {
      this.canPlay = false
      this.clearBufferItv()
      this.bufferedProgress = 0
      this.reset()
      this.file = url
      this.setBufferItv()
    },

    playOrPause () {
      eventTrack('007003');

      if (this.canPlay) {
        this.playing ? this.pause() : this.play()
      }
    },

    play () {
      if(this.isfirstLoad) {
        this.audio.load()
        this.isfirstLoad = false
      }
      this.playing = true
      let minBufferProgress = 0
      if(IOS) {
        minBufferProgress = 90
      }
      this.isloading = true
      this.$emit('loadCompleted', false)
      let timer = setInterval(() => {
        if(this.bufferedProgress >= minBufferProgress) {
          this.clearItv()
          this.isloading = false
          this.$emit('loadCompleted', true)
          if(this.playing) {
            this.playFun()
            clearInterval(timer)
          }
        }
      }, 30)
    },

    playFun () {
      this.audio.play()
      this.currentTime = this.audio.currentTime
      this.progress = this.currentTime / this.totalTime * 100
      this.setItv()
    },

    load() {
      this.audio.load()
    },

    pause () {
      this.clearItv()
      this.playing = false
      this.audio.pause()
    },

    reset () {
      this.clearItv()
      this.progress = 0
      this.playing = false
      this.audio.currentTime = 0
      this.currentTime = 0
      this.pause()
    },

    setItv () {
      this.sliderChangeInterval = setInterval(() => {
        if (this.leftTime <= 1) {
          this.clearItv()
          this.reset()
          return false
        }
        this.progress += this.step
        this.currentTime++
        this.leftTime--
      }, 1000)
    },

    clearItv () {
      window.clearInterval(this.sliderChangeInterval)
    },

    setBufferItv () {
      this.bufferInterval = setInterval(() => {
        let buffer = this.audio.buffered
        if (buffer.length === 0) return
        let bufferedTime = buffer.end(buffer.length - 1)
        this.bufferedProgress = bufferedTime / this.totalTime * 100
        if (this.bufferedProgress >= 100) {
          this.clearBufferItv()
        }
      }, 1000)
    },

    clearBufferItv () {
      window.clearInterval(this.bufferInterval)
    },

    changeProgress (val:number) {
      eventTrack('007001')

      if (!this.playing) {
        this.audio.play()
        this.playing = true
        this.setItv()
      }
      this.audio.currentTime = this.totalTime * val / 100
      this.currentTime = this.audio.currentTime
    },

    prev () {
      eventTrack('007002')

      if(!this.isFirstAudio) {
        this.$emit('prev')
      }
    },

    next () {
      eventTrack('007004')

      if(!this.isLastAudio) {
        this.$emit('next')
      }
    }
  }
})
</script>

<style scoped>
.player__wrapper {
  padding: 0px 5px 0 5px;
  background-color: transparent;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  flex-direction: column;
  align-items: center;
  position: relative;
}
.player__progress {
  width: 100%;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.player__progress .time {
  width: 100%;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  justify-content: space-between;
}
.player__progress .time-now,
.player__progress .time-all {
  color: #fff;
}
.player__progress-bar {
  width: 100%;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  justify-content: center;
}
.player__btn-group {
  position: absolute;
  top: 45px;
  left: 0;
  padding: 0 20%;
  z-index: 2200;
  box-sizing: border-box;
  /*margin-top: 10px;*/
  width: 100%;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  justify-content: space-between;
  align-items: center;
  transition: 0.3s all;
}
.player__btn-group .play,
.player__btn-group .pause {
  width: 30px;
  height: 30px;
}
.player__btn-group .play.disabled,
.player__btn-group .pause.disabled,
.player__btn-group .prev.disabled,
.player__btn-group .next.disabled {
  opacity: 0.6;
}
.player__btn-group .prev,
.player__btn-group .next {
  width: 25px;
  height: 25px;
}
.player__btn-group .prev {
  background-image: url('../../assets/images/icon_fm_qianyihsou@2x.png');
  background-size: contain;
  background-repeat: no-repeat;
}

.player__btn-group .next {
  transform: rotate(180deg);
  background-image: url('../../assets/images/icon_fm_qianyihsou@2x.png');
  background-size: contain;
  background-repeat: no-repeat;
}

.player__btn-group .play {
  background-image: url('../../assets/images/icon_fm_bofang@2x.png');
  background-size: contain;
  background-repeat: no-repeat;
}

.player__btn-group .pause {
  background-image: url('../../assets/images/icon_fm_zanting@2x.png');
  background-size: contain;
  background-repeat: no-repeat;
}
</style>
